import pandas as pd
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import LabelEncoder
from matplotlib import rcParams

# 设置字体为 SimHei（黑体）
rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

def perform_pca(csv_file, target_column=None, n_components=2, output_file="pca_scatter.png"):

    df = pd.read_excel(csv_file)

    # 如果有 target_column，则分离特征和标签
    if target_column:
        X = df.drop(columns=[target_column]).values  # 特征数据
        y = df[target_column].values  # 分类标签
        # 将类别标签编码为数字（如果是字符串）
        label_encoder = LabelEncoder()
        y_encoded = label_encoder.fit_transform(y)
        target_names = label_encoder.classes_  # 类别名称
    else:
        X = df.values  # 如果没有 target_column，则所有列都是特征
        y_encoded = None
        target_names = None

    # 执行 PCA
    pca = PCA(n_components=n_components)
    X_pca = pca.fit_transform(X)

    # 输出解释方差比例
    print("各主成分的解释方差比例：", pca.explained_variance_ratio_)
    print("累计解释方差比例：", sum(pca.explained_variance_ratio_))

    # 绘制降维结果
    plt.figure(figsize=(8, 6))

    if y_encoded is not None:
        # 有类别信息时，按类别绘制散点图
        colors = plt.cm.Set1.colors  # 默认颜色表
        for i, target_name in enumerate(target_names):
            plt.scatter(
                X_pca[y_encoded == i, 0],
                X_pca[y_encoded == i, 1],
                label=target_name,
                alpha=0.8,
                s=50
            )
    else:
        # 没有类别信息时，绘制无分类的散点图
        plt.scatter(X_pca[:, 0], X_pca[:, 1], alpha=0.8, s=50)

    # 添加标题和标签
    plt.xlabel("Principal Component 1")
    plt.ylabel("Principal Component 2")
    plt.title("抗压强度PCA Result")
    if y_encoded is not None:
        plt.legend(loc="best")
    plt.grid()

    # 保存图像
    plt.savefig(output_file)
    print(f"散点图已保存为: {output_file}")

    # 显示图像
    plt.show()
    print(X_pca[:, 0])
    print(X_pca[:, 1])

# 示例调用
perform_pca('抗压强度_修改后.xlsx', target_column=None, n_components=2)
